package com.chen.script.config;

import cn.hutool.core.util.StrUtil;
import com.chen.base.utils.PropertyUtil;
import com.chen.base.utils.SpringContextHolder;
import com.chen.script.annotation.Job;
import com.chen.script.constant.JobConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.config.IntervalTask;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * 定时任务配置类
 * @author ChenJinLong
 */
@Slf4j
@Configuration
public class SchedulingConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar registrar) {
        Map<Object, Map<Method, Job>> beansMap = SpringContextHolder.getBeansByMethodAnnotate(Job.class);

        for (Object bean : beansMap.keySet()) {
            for (Map.Entry<Method, Job> entry : beansMap.get(bean).entrySet()) {
                Job job = entry.getValue();
                // 拼接打开定时任务的key
                String openKey = job.value() + ".enable";
                if (StrUtil.isNotBlank(job.enable())){
                    openKey = job.enable();
                }
                Boolean isEnable = PropertyUtil.getProperty(openKey, Boolean.class);
                if (isEnable){
                    Method method = entry.getKey();
                    Runnable task = task(bean, method);

                    // job类型
                    String type = "cron";
                    String typeValue = getValue(job, ".type");
                    if (StrUtil.isNotBlank(typeValue)){
                        type = typeValue;
                    }

                    if (JobConstant.CRON.equalsIgnoreCase(type)){
                        // 获取cron的value
                        String cron = getValue(job, ".cron");
                        registrar.addCronTask(task, cron);

                    }else if (JobConstant.DELAY.equalsIgnoreCase(type)){
                        // 获取delay的value
                        String initDelayKey = job.value() + ".initDelay";
                        long initDelay = PropertyUtil.getProperty(initDelayKey, Long.class);
                        long delay = Long.parseLong(getValue(job, ".delay"));

                        IntervalTask intervalTask = new IntervalTask(task, delay, initDelay);
                        registrar.addFixedDelayTask(intervalTask);
                    }
                }
            }
        }

        List<CronTask> tasks = registrar.getCronTaskList();
        log.info("Scheduled tasks: {}", tasks.size());
    }

    private String getValue(Job job, String suffix){
        return PropertyUtil.getProperty(job.value() + suffix);
    }

    private Runnable task(Object bean, Method method){
        Object[] args = new Object[method.getParameterCount()];
        return () -> {
            try {
                method.invoke(bean, args);
            } catch (Exception e) {
                log.error("执行定时任务异常: ", e);
            }
        };
    }
}
